import utils from "./utils";
import hmacSha1 from "./hmac-sha1";
import { ByteUtils } from '../utils/ByteUtils'
import { DesUtils } from '../utils/DesUtils'

export class Gen17CodeUtils {

    generateTOTP(dKey, eKey, time, cardSnr, time3) {

        let dKeyLength = dKey.length;
        let eKeyLength = eKey.length;
        let cardSnrLength = cardSnr.length;
        let digitLen = 6;

        console.log(`dKeyLength = ${dKeyLength},eKeyLength = ${eKeyLength},cardSnrLength = ${cardSnrLength},digitLen = ${digitLen}`);

        let uLongArray = new Uint32Array(new ArrayBuffer(2 * 4));
        uLongArray[0] = time / 1000;  //secondTime
        uLongArray[1] = uLongArray[0] / (time3 * 60);  //minutesTime
        console.log(`time = ${time},secondTime = ${uLongArray[0]},minutesTime = ${uLongArray[1]}`);

        let totalSec = parseInt((uLongArray[0] % (time3 * 60)));
        let minOffset = parseInt(totalSec / 60);
        let secOffset = parseInt(totalSec % 60);
        console.log(`totalSec = ${totalSec},minOffset = ${minOffset},secOffset = ${secOffset}`);

        //minutesTime 转 8位byte
        let timeArray = new Uint8Array(new ArrayBuffer(8));
        utils.long2Char(timeArray, 8, uLongArray[1], 0);
        console.log(`timeArray = ${ByteUtils.bytesToHexStr(timeArray)}`);

        let d1 = this.generateTOTPSha1(dKey, dKeyLength, timeArray, 8, digitLen);

        //step1: 将d1转化为 16进制byte数组D1如 123456 转为0x12,0x34,0x56  end
        let d1Bcd = utils.decToBCD(d1, digitLen / 2);
        console.log(`d1Bcd = ${ByteUtils.bytesToHexStr(d1Bcd)}`);

        //step2: 使用下面规则将cardsnr转化成Cardsnr1
        let cardSnr1 = new Uint8Array(new ArrayBuffer(cardSnrLength));
        for (let i = 0; i < 3; i++) {
            cardSnr1 [i] = cardSnr[i] ^ (~d1Bcd[i]);
        }
        cardSnr1 [3] = cardSnr[3] ^ (~d1Bcd[0]);
        console.log(`cardSnr1 = ${ByteUtils.bytesToHexStr(cardSnr1)}`);

        //step3: 将Secoffset(16进制格式) 与 Cardsnr1每个字节异或得到4个字节的Cardsnr1’ 转化为一个10位数字(不够10位数字的前面补’0’),记为K
        let cardSnr2 = new Uint8Array(new ArrayBuffer(cardSnrLength));
        for (let i = 0; i < 4; i++) {
            cardSnr2[i] = cardSnr1[i] ^ secOffset;
        }
        console.log(`cardSnr2 = ${ByteUtils.bytesToHexStr(cardSnr2)}`);
        let cardSnrK = utils.char2Long(cardSnr2, 4, 0, 4);
        cardSnrK = "" + cardSnrK;
        while (cardSnrK.length < 10) {
            cardSnrK = "0" + cardSnrK;
        }
        console.log(`cardSnrK = ${cardSnrK}`);

        //step4: 将1位Minoffset||2位Secoffset||10位K||6位d1组成一个19位的数字字符串
        if (secOffset.toString().length < 2) {
            secOffset = "0" + secOffset;
        }
        let number19 = "" + minOffset + secOffset + cardSnrK + ByteUtils.bytesToHexStr(d1Bcd);
        console.log(`number19 = ${number19}`);

        let number19Sort = "";
        let sort = [5, 2, 4, 8, 1, 3, 9, 7, 6, 10, 16, 18, 0, 15, 11, 13, 12, 17, 14];
        for (let i = 0; i < sort.length; i++) {
            number19Sort += number19.charAt(sort[i]);
        }
        console.log(`number19Sort = ${number19Sort}`);

        let number20Sort = "0" + number19Sort;
        console.log(`number20Sort = ${number20Sort}`);

        //step5: 新数组标记为QR
        let qr = new Uint8Array(new ArrayBuffer(10));
        utils.str2Bcd(number20Sort, number20Sort.length, qr);
        console.log(`qr = ${ByteUtils.bytesToHexStr(qr)}`);

        //---计算mac---
        //3des向量为 eKey 前8位，秘钥e 为后8位
        let desV = new Uint8Array(new ArrayBuffer(8));
        utils.charArrayCopy(eKey, 0, desV, 0, 8);
        let desEKey = new Uint8Array(new ArrayBuffer(8));
        utils.charArrayCopy(eKey, 8, desEKey, 0, 8);
        //3des秘钥为 eKey后8位+eKey后8位取反
        let desKey = new Uint8Array(new ArrayBuffer(16));
        utils.charArrayCopy(desEKey, 0, desKey, 0, 8);
        for (let i = 0; i < desEKey.length; i++) {
            desKey[i + 8] = ~desEKey[i];
        }
        // console.log(`desV=${ByteUtils.bytesToHexStr(desV)},desEKey=${ByteUtils.bytesToHexStr(desEKey)},desKey=${byteUtils.bytesToHexStr(desKey)}`);

        let macArray = new DesUtils().pboc3desMAC(qr, desKey, desV);
        console.log(`macArray = ${macArray}`);
        macArray = ByteUtils.hexStrToBytes(macArray);

        let finalMac = new Uint8Array(new ArrayBuffer(2));
        finalMac[0] = macArray[0] ^ macArray[2];
        finalMac[1] = macArray[1] ^ macArray[3];

        let mac = utils.char2Int(finalMac, finalMac.length, 0);
        console.log(`mac = ${mac}`);
        mac = "" + mac;
        while (mac.length < 5) {
            mac = "0" + mac;
        }

        //将2位业务代码||第3步生成的19位数字||第4步生成的5位数字共26个数字作为最终的二维码
        let qrCode = `17${number19Sort}${mac}`;
        // console.log(`newNumberArray = ${number19Sort}`)
        qrCode = qrCode.replaceAll(",", "");

        console.log(`qrCode = ${qrCode}`)
        return qrCode;
    }

    generateTOTPSha1(dKey, dKeyLength, data, dataLength, digitLen) {

        console.log(`dKey = ${ByteUtils.bytesToHexStr(dKey)}`);
        console.log(`dKeyLength = ${dKeyLength}`);

        let length = 20;
        let array = new Uint8Array(new ArrayBuffer(20));
        array = hmacSha1.hmac_sha1(dKey, dKeyLength, data, dataLength);
        array = ByteUtils.hexStrToBytes(array);

        console.log(`array = ${ByteUtils.bytesToHexStr(array)}`);

        let offset = array[length - 1] & 0xf;
        let binary = ((array[offset] & 0x7f) << 24) | ((array[offset + 1] & 0xff) << 16) | ((array[offset + 2] & 0xff) << 8) | (array[offset + 3] & 0xff);

        let DIGITS_POWER = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000];
        return binary % DIGITS_POWER[digitLen];
    }
}

const gen17CodeUtils = new Gen17CodeUtils();
export default gen17CodeUtils
